package widget.bar;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import library.logger.Logger;


/**
 * Created by Mr.Fan on 2016/11/12.
 */

public abstract class Bar<T extends Bar> {

    @NonNull
    private SystemBar systemBar;
    private T bar;
    private boolean support = true;
    private boolean transparent = false;
    private boolean translucent = true;
    private Integer color;
    private Integer alpha;

    protected Bar(@Nullable SystemBar systemBar) {
        this.systemBar = systemBar;
        this.bar = (T) this;
    }

    protected SystemBar getSystemBar() {
        return systemBar;
    }

    public boolean apply(@NonNull Activity activity) {
        if (activity != null)
            return apply(activity.getWindow());
        return false;
    }

    public boolean apply(@NonNull Window window) {
        return systemBar.apply(window);
    }

    public T support(boolean support) {
        this.support = support;
        return this.bar;
    }

    public T transparent() {
        this.transparent = true;
        this.translucent = false;
        return this.bar;
    }

    public T translucent() {
        this.translucent = true;
        this.transparent = false;
        return this.bar;
    }

    public T color(int color) {
        this.transparent = false;
        this.translucent = false;
        this.color = color;
        return this.bar;
    }

    /**
     * 0.0~1.0
     *
     * @param alpha
     * @return
     */
    public T alpha(float alpha) {
        return alpha((int) (alpha * 0xFF));
    }

    /**
     * 0~255
     *
     * @param alpha
     * @return
     */
    public T alpha(int alpha) {
        this.transparent = false;
        this.translucent = false;
        this.alpha = alpha;
        return this.bar;
    }

    public boolean isSupport() {
        return support;
    }

    public Integer getColor() {
        return color;
    }

    public Integer getAlpha() {
        return alpha;
    }

    public boolean isTransparent() {
        return transparent;
    }

    public boolean isTranslucent() {
        return translucent;
    }

    /*
     * ******************************************************************************************
     * Help Method
     * ******************************************************************************************
     */

    protected <T extends View> T getView(ViewGroup parent, Class<T> type) {
        final int count = parent.getChildCount();
        for (int i = count - 1; i > 0; i--) {
            View view = parent.getChildAt(i);
            if (view != null && view.getClass() == type) {
                return (T) view;
            }
        }
        return null;
    }

    protected boolean hasFlag(int options, int flag) {
        if ((options & flag) != 0) {
            return true;
        }
        return false;
    }

    protected int clearFlag(int flags, int mask) {
        return (flags & ~mask) | (0 & mask);
    }


    protected int alphaColor(Integer color, Integer alpha) {
        if (color == null)
            color = getSystemBar().getMainColor();
        if (alpha == null)
            return color;

        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.argb(alpha, red, green, blue);
    }

    protected void D(String format, Object... args) {
        Logger.debug(format, args);
    }

    /*
     * ******************************************************************************************
     * Inner Class 仅用于类型判断以避免重复添加view
     * ******************************************************************************************
     */

    protected static class BarView extends View {

        public BarView(Context context) {
            super(context);
        }
    }

    protected static final class BarDrawable extends GradientDrawable {
        private Integer topColor;
        private Integer bottomColor;

        public BarDrawable() {
        }

        private BarDrawable(Orientation orientation, int[] colors) {
            super(orientation, colors);
            this.topColor = colors[0];
            this.bottomColor = colors[1];
        }

        public void setTopColor(Integer topColor) {
            this.topColor = topColor;
        }

        public void setBottomColor(Integer bottomColor) {
            this.bottomColor = bottomColor;
        }

        public BarDrawable getDrawable() {
            final int[] colors = new int[]{Color.BLACK, Color.BLACK};
            if (topColor != null)
                colors[0] = topColor;
            if (bottomColor != null)
                colors[1] = bottomColor;
            return new BarDrawable(Orientation.TOP_BOTTOM, colors);
        }
    }

    protected static final class FitDrawable extends LayerDrawable {
        private int layerInsetTop;
        private int layerInsetBottom;

        /**
         * Creates a new layer drawable with the list of specified layers.
         *
         * @param layers a list of drawables to use as layers in this new drawable,
         *               must be non-null
         */
        public FitDrawable(Drawable[] layers) {
            super(layers);
        }

        @Override
        public void setLayerInset(int index, int l, int t, int r, int b) {
            layerInsetTop = t;
            layerInsetBottom = b;
            super.setLayerInset(index, l, t, r, b);
        }

        public void setLayerInsetTop(int index, int layerInsetTop) {
            setLayerInset(index, 0, layerInsetTop, 0, layerInsetBottom);
        }

        public void setLayerInsetBottom(int index, int layerInsetBottom) {
            setLayerInset(index, 0, layerInsetTop, 0, layerInsetBottom);
        }

        public int getLayerInsetTop() {
            return layerInsetTop;
        }

        public int getLayerInsetBottom() {
            return layerInsetBottom;
        }
    }
}
